<template>
  <div class="calendar">
    <div style="height: 40px">
      <el-button
        size="mini"
        style="background-color: #262c42; border: none; color: #cff5f6"
        @click="clickToday"
        >今天</el-button
      >
      <el-button
        type="info"
        size="mini"
        icon="el-icon-arrow-left"
        style="background-color: #262c42; border: none; color: #9ba1ad"
        @click="handleQuickChange('prev')"
      ></el-button>
      <span style="color: #f4f5f6; font-size: 16px; padding: 0px 10px">{{
        curYear + "年" + (curMonth + 1) + "月"
      }}</span>
      <el-button
        type="info"
        size="mini"
        icon="el-icon-arrow-right"
        style="background-color: #262c42; border: none; color: #9ba1ad"
        @click="handleQuickChange('next')"
      ></el-button>
    </div>
    <table class="calendar-table" :style="{ width }">
      <thead>
        <tr>
          <th v-for="(item, i) in weeks" :key="i">{{ item }}</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(dates, i) in res" :key="i">
          <td
            v-for="(item, index) in dates"
            :key="index"
            :class="{
              notCurMonth: !item.isCurMonth,
              currentDay: item.date === curDate,
              selectDay: item.isSelected,
              rangeSelectd: item.isRangeSelected,
              weekend: item.isWeekend,
            }"
            @click="handleItemClick(item, i, index)"
            @mouseover="handleItemMove(item, i, index)"
          >
            <!-- <span>{{ item.date.split('-').slice(1).join('-') }}</span> -->
            <span>{{ item.date }}</span>
            <slot :data="item" />
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
import {
  getDate_Api, //演练日历
} from "@/api/automated/DisasterRecovery.js";
import {
  getDaysInMonth,
  handleCrateDate,
  handleCreateDatePicker,
  parseTime,
} from "./index";
export default {
  components: {},
  props: {
    selectMode: {
      type: String,
      default: "click",
      // default: "false",
    },
    startOfWeek: {
      type: Number,
      default: 1,
    },
    canSelect: {
      type: Boolean,
      default: false,
    },
    width: {
      type: String,
      default: "100%",
    },
    tbodyHeight: {
      type: String,
      default: "60px",
    },
  },
  data() {
    return {
      drill_date: {
        startTime: "2023-10-10",
        endTime: "2023-11-20",
      }, //演练日历
      monthOptions: [],
      yearOptions: [],
      weeks: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
      curYear: new Date().getFullYear(), // 当前年
      curMonth: new Date().getMonth(), // 当前月
      days: 0, // 当前月总共天数
      curDate: parseTime(new Date().getTime(), null, "day"), // 当前日期 yyyy-MM-dd 格式，用来匹配是否是当前日期
      prevDays: [], // 非当前月的上一月展示的日期
      rearDays: [], // 非当前月的下一月展示的日期
      curDays: [], // 当前月的日期
      showDays: [], // 总共展示的42个日期
      res: [], // 二维数组
      selectedDates: [
        {
          date: "12日",
          isCurMonth: true,
          isRangeSelected: false,
          isSelected: true,
        },
        {
          date: "13日",
          isCurMonth: true,
          isRangeSelected: false,
          isSelected: true,
        },
        {
          date: "14日",
          isCurMonth: true,
          isRangeSelected: false,
          isSelected: true,
        },
        {
          date: "15日",
          isCurMonth: true,
          isRangeSelected: false,
          isSelected: true,
        },

        {
          date: "16日",
          isCurMonth: true,
          isRangeSelected: false,
          isSelected: true,
        },
        {
          date: "17日",
          isCurMonth: true,
          isRangeSelected: false,
          isSelected: true,
        },
        {
          date: "18日",
          isCurMonth: true,
          isRangeSelected: false,
          isSelected: true,
        },
        {
          date: "19日",
          isCurMonth: true,
          isRangeSelected: false,
          isSelected: true,
        },
        {
          date: "20日",
          isCurMonth: true,
          isRangeSelected: false,
          isSelected: true,
        },
        {
          date: "21日",
          isCurMonth: true,
          isRangeSelected: false,
          isSelected: true,
        },
      ], // 选中的日期
      selectedMode: false, // true表示点击， false表示滑动
      moveIndex: [], // 两个，第一个是起始，第二个是结束
      canMove: false, // 当moveIndex数组有一个值时，可以触发滑动
    };
  },
  computed: {},
  watch: {
    curMonth: {
      handler(val) {
        this.handleGetDays(this.curYear, val, this.startOfWeek);
        this.changeStateByRange();
      },
    },
    curYear: {
      handler(val) {
        this.handleGetDays(val, this.curMonth, this.startOfWeek);
        this.changeStateByRange();
      },
    },
  },
  created() {
    this.getDate(); //获取演练日历
    this.weeks.unshift(...this.weeks.splice(this.startOfWeek - 1)); // 渲染表头
    this.handleGetDays(this.curYear, this.curMonth, this.startOfWeek); // 渲染表格内容
    this.selectedMode = this.selectMode === "click"; // 判断选择模式
  },
  mounted() {
    this.monthOptions = handleCreateDatePicker().months;
    this.yearOptions = handleCreateDatePicker().years;
  },
  methods: {
    //获取演练日历
    getDate() {
      getDate_Api().then((res) => {
        this.drill_date = res.data;
        this.changeStateByRange();
      });
    },
    //解析演练日历请求结果的时期范围，改变样式
    changeStateByRange() {
      const startTime = Date.parse(this.drill_date.startTime); //演练日历开始时间
      const endTime = Date.parse(this.drill_date.endTime); //演练日历结束时间
      this.res.forEach((item) => {
        item.forEach((ele) => {
          const targetTime = Date.parse(ele.completeDate);
          //如果日期在 开始日期和结束日期之内，改变状态
          if (targetTime >= startTime && targetTime <= endTime) {
            ele.isSelected = true;
          }
        });
      });
    },
    handleGetDays(year, month, startOfWeek) {
      this.showDays = []; //显示的天
      this.days = getDaysInMonth(year, month);
      let firstDayOfWeek = new Date(`${year}-${month + 1}-01`).getDay();

      // 处理周起始日
      const obj = {
        0: "周日",
        1: "周一",
        2: "周二",
        3: "周三",
        4: "周四",
        5: "周五",
        6: "周六",
      };
      const firstDayInCN = obj[firstDayOfWeek];
      const index = this.weeks.indexOf(firstDayInCN);

      this.prevDays = handleCrateDate(year, month, 1, index + 1, "prev");
      this.rearDays = handleCrateDate(
        year,
        month,
        1,
        42 - this.days - index,
        "rear"
      );
      this.curDays = handleCrateDate(year, month, 1, this.days);

      this.showDays.unshift(...this.prevDays);
      this.showDays.push(...this.curDays);
      this.showDays.push(...this.rearDays);
      this.res = this.handleFormatDates(this.showDays);
    },
    //转成二维数组的方法
    handleFormatDates(arr, size = 7) {
      // 传入长度42的原数组，最终转换成二维数组
      const arr2 = [];
      for (let i = 0; i < size; i++) {
        const temp = arr.slice(i * size, i * size + size);
        arr2.push(temp);
      }
      return arr2;
    },
    //切换月份
    handleQuickChange(type) {
      if (type === "prev") {
        this.curMonth--;
        if (this.curMonth === -1) {
          this.curMonth = 11;
          this.curYear -= 1;
        }
      } else if (type === "next") {
        this.curMonth++;
        if (this.curMonth === 12) {
          this.curMonth = 0;
          this.curYear += 1;
        }
      }
    },

    //点击节点
    handleItemClick(item, i, j) {
      if (!this.canSelect) return; //canSelect==false不能选择
      if (this.selectedMode) {
        this.$nextTick(() => {
          this.res[i][j].isSelected = !this.res[i][j].isSelected;
          if (this.res[i][j].isSelected) {
            this.selectedDates.push(this.res[i][j].date);
            this.selectedDates = Array.from(new Set(this.selectedDates));
          } else {
            this.selectedDates.splice(this.selectedDates.indexOf(item.date), 1);
          }
          this.$emit("dateSelected", this.selectedDates);
        });
      } else {
        // 滑动模式下，第一次点击是起始，第二次点击是结束
        const index = i * 7 + j;
        this.canMove = true;
        if (this.moveIndex.length === 1) {
          this.canMove = false;
        }
        if (this.moveIndex.length === 2) {
          this.showDays.forEach((item) => {
            item.isSelected = false;
            item.isRangeSelected = false;
          });
          this.canMove = true;
          this.moveIndex.length = 0;
        }
        this.moveIndex.push(index);
        this.moveIndex.sort((a, b) => a - b);
        this.selectedDates = this.showDays.slice(
          this.moveIndex[0],
          this.moveIndex[1] + 1
        );
        this.selectedDates.length !== 0 &&
          this.$emit("dateSelected", this.selectedDates);
      }
    },
    //拉取节点
    handleItemMove(data, i, j) {
      //判断可不可以移动
      if (this.canMove && !this.selectedMode) {
        const index = i * 7 + j;
        this.showDays.forEach((item) => {
          item.isSelected = false;
          item.isRangeSelected = false;
        });
        // 让第一个日期和最后一个日期显示蓝色高亮
        this.showDays[index].isSelected = true;
        this.showDays[this.moveIndex[0]].isSelected = true;

        // 不同情况的判断，当用户的鼠标滑动进日期的索引小于起始日期的索引，要做if else处理
        if (this.moveIndex[0] < index) {
          for (let i = this.moveIndex[0] + 1; i < index; i++) {
            this.showDays[i].isRangeSelected = true;
          }
        } else {
          for (let i = index + 1; i < this.moveIndex[0]; i++) {
            this.showDays[i].isRangeSelected = true;
          }
        }
      }
    },
    //点击今天按钮
    clickToday() {
      this.curYear = new Date().getFullYear(); // 当前年
      this.curMonth = new Date().getMonth(); // 当前月
    },
  },
};
</script>

<style scoped lang="scss">
.calendar {
  height: 100%;
  width: 100%;
  //   display: flex;
  //   align-items: center;
  //   justify-content: center;
  //   flex-direction: column;
  color: #ffffff;
}
.calendar-table {
  height: calc(100% - 40px);
  table-layout: fixed;
  border-collapse: collapse;
  transition: 0.3s;
  thead tr {
    height: 25px;
    font-size: 12px;
    th {
      cursor: pointer;
      border-right: 1px solid #242739;
      border-top: 1px solid #242739;
      &:first-child {
        border-left: 1px solid #242739;
      }
    }
  }
  tbody tr {
    &:first-child td {
      border-top: 1px solid #242739;
    }
    td {
      cursor: pointer;
      border-right: 1px solid #242739;
      border-bottom: 1px solid #242739;
      box-sizing: border-box;
      padding: 5px;
      text-align: right;
      position: relative;
      &:first-child {
        border-left: 1px solid #242739;
      }
      span {
        display: inline-block;
        position: absolute;
        top: 0;
        right: 0;
        width: 40px;
        height: 40px;
        text-align: center;
      }
    }
  }
}

.notCurMonth {
  color: #4b536b;
}
.currentDay {
  color: #fff;
  span {
    color: #409eff;
    font-weight: 550;
  }
}
.selectDay {
  &::after {
    content: "";
    width: calc(100% + 1px);
    height: 30%;
    position: absolute;
    left: 0;
    top: 40%;
    background-color: #27bb70;
  }
}
.rangeSelectd {
  color: #606266;
  background-color: #dee2e9;
}
.weekend {
  color: #f73131;
}
</style>

